/** 通用热键脚本(utf-8 with BOM)
  包括设置ahk_exe,连发,一般技能,预设读取
  游戏键4个,热键5个,用逗号分隔
  连发键可以留空表示不设定
  
  By setycyas @2023-01-17 10:22
*/

/* 全局
*/{

  ;** 全局设置
  #NoEnv
  #Warn
  #MaxThreadsPerHotkey 1
  SendMode Input
  SetWorkingDir %A_ScriptDir%
  
  ;** 库调用
  #Include ..\MyAhkModules\MyFuns.ahk ;自制常用函数库,所有导出函数以MyFuns_开头
  #Include ..\MyAhkModules\MyKey.ahk ;按键相关库,所有导出函数以MyKey_开头
  #Include ..\MyAhkModules\MyFaceDetector.ahk ;方向检测,用MyFaceDetector_setup()函数设置
  #Include ..\MyAhkModules\MyWinkawaks.ahk ;导入自定义的Winkawaks通用快捷键,用MyWinKawaks_setHotkeys()函数设置
  #Include ..\MyAhkModules\MyNebula.ahk ;导入自定义的Nebula通用快捷键,用MyNebula_setHotkeys()函数设置

  ;** 全局常量
  ;可能选择的exe字符串表,用于gui组件,按组件格式写
  global EXE_LIST := "WinKawaks.exe|X-Zone.exe|fbas.exe|Nebula.exe"
  ;技能名称字符串表,用于gui组件,按组件格式写
  global SKILL_LIST := "空|下前A|下上A|下B|下前B|前A|A后防御|前C|前冲A|后前A|龙2小跳BB|快速旋转A"
  ;预设名称字符串与预设表,每一个预设都按顺序指定4个热键的效果
  global PRESET_ARRAY := ["龙2暗黑秘影", "三国志2", "119白黄", "119白张"]
  global PRESET_TABLE := {}
  PRESET_TABLE["龙2暗黑秘影"] := ["下前A", "下上A", "A后防御", "下前B", "快速旋转A"]
  PRESET_TABLE["三国志2"] := ["下上A", "空", "空", "下B", "快速旋转A"]
  PRESET_TABLE["119白黄"] := ["下前A", "前A", "下上A", "前冲A", "空"]
  PRESET_TABLE["119白张"] := ["后前A", "下前A", "下上A", "前冲A", "空"]
  ;连发按键时按住键的时长
  global AUTOFIRE_DURATION := 25
  ;游戏键数量
  global NUM_OF_GAME_KEYS := 4
  ;热键数量
  global NUM_OF_SKILL_KEYS := 5
  ;最大连发频率
  global MAX_FPS := 30
  
  ;** 绑定gui组件的全局变量,以G开头
  ;exe选择
  global Gexe := "WinKawaks.exe"
  ;游戏按键设定
  global GgameKeys := "x,e,d,s"
  ;连发键设置
  global GautoFireKey := "w"
  ;技能快捷键设定
  global GmyKeys := "q,2,3,r,a"
  ;各个热键对应的技能选择,默认为空,数量必须与常量NUM_OF_SKILL_KEYS相等
  global Gskill1 := "空", Gskill2 := "空", Gskill3 := "空", Gskill4 := "空", Gskill5 := "空"
  ;连发频率参数,设置上限为20,设置为0表示单发.矮人设置为7似乎好些,其他人可以10
  global GautoFireFPS := 10
  ;测试参数
  global GtestParam1 := 750, GtestParam2 := 500, GtestParam3 := 500 ;
  
  ;** 全局变量
  ;重设热键次数,如果是0则表示之前没设置过
  global resetTimes := 0
  ;游戏本身的按键,读取gui中的游戏按键设定,数量必须与常量NUM_OF_GAME_KEYS相等
  global key1 := "", key2 := "", key3 := "", key4 := ""
  ;自设技能键,读取gui中的技能快捷键设定
  global myKey1 := "", myKey2 := "", myKey3 := "", myKey4 := "", myKey5 := ""

}

/* 操作与技能函数 
*/{

  ;** 技能函数,使用中文
  空(){
    return
  }
  下前A(){
    local face := MyFaceDetector_getFace()
	MyKey_inputSkill(["down", face, key1], [30, 30, 30])
  }
  下上A(){
    MyKey_press("down", 25)
	sleep, 25
    MyKey_pressKeys(["up", key1], [25], 25)
  }
  下B(){
    MyKey_pressKeys(["down", key2], [25], 25)
  }
  下前B(){
    local face := MyFaceDetector_getFace()
	MyKey_inputSkill(["down", face, key2], [30, 30, 30])
  }
  前A(){
    local face := MyFaceDetector_getFace()
	MyKey_pressKeys([face, key1], [25], 25)
  }
  A后防御(){
    local thisHotkey := MyFuns_getHotkey(A_ThisHotkey) ;触发技能的热键
    local backFace := MyFaceDetector_getBackFace()
    send, {%key1% down}
    sleep, 50
    MyKey_press(backFace, 200)
    while (GetKeyState(thisHotkey)) {
      sleep, 20
    }
    send, {%key1% up}
  }
  前C(){
	local face := MyFaceDetector_getFace()
	MyKey_pressKeys([face, key3], [25], 25)
  }
  前冲A(){
    local face := MyFaceDetector_getFace()
    MyKey_press(face, 30)
    sleep, 50
    send, {%face% down}
    sleep, 50
    send, {%key1% down}
    sleep, 50
    send, {%key1% up}
    sleep, 50
    send, {%face% up}
  }
  后前A(){
    local face := MyFaceDetector_getFace()
    local backFace := MyFaceDetector_getBackFace()
    MyKey_press(backFace, 50)
    sleep, 50
    MyKey_pressKeys([face, key1], [30])
  }
  龙2小跳BB(){
    MyKey_press(key2, 30)
    sleep, 50
    MyKey_press(key2, 30)
    sleep, 100
  }
  快速旋转A(){
    local thisHotkey := MyFuns_getHotkey(A_ThisHotkey) ;触发技能的热键
    while (GetKeyState(thisHotkey)) {
      MyKey_press("up", 20)
      sleep, 20
      MyKey_press("right", 20)
      sleep, 20
      MyKey_press("down", 20)
      sleep, 20
      MyKey_pressKeys(["left", key1], [20], 20)
      sleep, 20
    }
  }
  
  ;** 其他需要使用的函数

}

/* gui设定与响应函数 
*/{

  ;** 设置gui
  setupGui(){
    local k, v ;循环用临时变量
    Gui, New, , 通用热键脚本
    Gui, Add, Tab3, , 初始设定|热键设定|参数设定 ;标签页分组
    Gui, Tab, 初始设定
    ;exe选择
    Gui, Add, Text, x+20 y+20, 选择exe：
    Gui, Add, ComboBox, xp+80 yp-3 W100 vGexe choose1, %EXE_LIST%
    ;游戏按键设定
    Gui, Add, Text, xp-80 yp+30, 4游戏键设定： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGgameKeys, %GgameKeys%
    ;连发键设定
    Gui, Add, Text, xp-80 yp+30, 连发键设定： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGautoFireKey, %GautoFireKey%
    ;技能热键设定
    Gui, Add, Text, xp-80 yp+30, 5热键设定： ;
    Gui, Add, Edit, xp+80 yp-3 W80 vGmyKeys, %GmyKeys%
    Gui, Tab, 热键设定
    ;技能热键绑定选择
    Gui, Add, Text, x+20 y+20, 热键1： ;
    Gui, Add, ComboBox, xp+80 yp-3 W100 vGskill1 choose1, %SKILL_LIST%
    Gui, Add, Text, xp-80 yp+30, 热键2： ;
    Gui, Add, ComboBox, xp+80 yp-3 W100 vGskill2 choose1, %SKILL_LIST%
    Gui, Add, Text, xp-80 yp+30, 热键3： ;
    Gui, Add, ComboBox, xp+80 yp-3 W100 vGskill3 choose1, %SKILL_LIST%
    Gui, Add, Text, xp-80 yp+30, 热键4： ;
    Gui, Add, ComboBox, xp+80 yp-3 W100 vGskill4 choose1, %SKILL_LIST%
    Gui, Add, Text, xp-80 yp+30, 热键5： ;
    Gui, Add, ComboBox, xp+80 yp-3 W100 vGskill5 choose1, %SKILL_LIST%
    ;参数设定
    Gui, Tab, 参数设定
    Gui, Add, Text, x+20 y+20, 连发频率(FPS)： ;次/秒
    Gui, Add, Edit, xp+80 yp-3 W60 vGautoFireFPS, %GautoFireFPS%
    Gui, Add, Text, xp-80 yp+30, 测试参数1： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGtestParam1, %GtestParam1%
    Gui, Add, Text, xp-80 yp+30, 测试参数2： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGtestParam2, %GtestParam2%
    Gui, Add, Text, xp-80 yp+30, 测试参数3： ;
    Gui, Add, Edit, xp+80 yp-3 W60 vGtestParam3, %GtestParam3%
    Gui, Tab
    ;提交数据
    Gui, Add, Button, gButtonSubmit_, 提交
    ;预设菜单
    for k, v in PRESET_ARRAY {
      Menu, PresetMenuItem, Add, %v%, MenuReadPreset ;每一个预设制作一个菜单项,名字为PresetMenuItem,点击时执行函数MenuReadPreset()
    }
    Menu, PresetMenuBar, Add, 读取预设, :PresetMenuItem ;制作菜单,并让所有名为PresetMenuItem的菜单项加入
    Gui, Menu, PresetMenuBar ;加入菜单
    ;加入状态栏
    Gui, Add, StatusBar, , 未设定热键
    ;显示gui
    Gui, Show, X1136 Y393
	Gui, +AlwaysOnTop
  }
  
  ;** gui响应
  ;提交数据时的行动,并不绑定按键,因为可能有多种提交方式
  submit_(){
    Gui, Submit, NoHide
	;首次设置,一些基础设定只能设置一次,设置后禁用
	if (resetTimes == 0){
      getKeySettings()
	  setNormalHotkeys()
	  GuiControl, Disable, Gexe
      GuiControl, Disable, GgameKeys
      GuiControl, Disable, GautoFireKey
      GuiControl, Disable, GmyKeys
	}
    setAutoFire() ;重设连发键
	setSkillKeys() ;重新设置技能热键,每次都要
	resetTimes += 1
    SB_SetText(A_Hour . ":" . A_Min . ":" . A_Sec . " 提交")
  }
  ;提交数据按钮
  ButtonSubmit_(){
    submit_()
    MsgBox, 数据提交成功!
  }
  ;读取预设,把各个技能的ComboBox修改成预设值但不提交数据
  MenuReadPreset(ItemName){
    loop, %NUM_OF_SKILL_KEYS% {
      GuiControl, ChooseString, Gskill%A_INDEX%, % PRESET_TABLE[ItemName][A_INDEX]
    }
    SB_SetText(A_Hour . ":" . A_Min . ":" . A_Sec . " 读取预设 - " . ItemName)
  }
  ;关闭gui退出
  GuiClose(guiHwnd){
    ExitApp
  }
  
}

/* 设置热键相关
*/{
  
  ;获取热键设定
  getKeySettings(){
    local keys := StrSplit(GgameKeys, ","), myKeys := StrSplit(GmyKeys, ",")
    loop, %NUM_OF_SKILL_KEYS% {
      key%A_Index% := keys[A_Index]
      myKey%A_Index% := myKeys[A_Index]
    }
  }

  ;设置一般热键,只在第一次设定时执行
  setNormalHotkeys(){
	;安装方向检测
	MyFaceDetector_setup(Gexe)
    ;根据exe选择,安装对应的通用热键
    
    ;安装WinKawaks.exe通用热键
    if (Gexe == "WinKawaks.exe") {
      MyWinKawaks_setHotkeys()
    }
    ;安装Nebula.exe通用热键
    if (Gexe == "Nebula.exe") {
      MyNebula_setHotkeys()
    }
  }
  
  ;设置连发
  setAutoFire(){
    local fps := MyFuns_arrMin([GautoFireFPS, MAX_FPS]) ;实际设定连发的频率,上限为MAX_FPS
    local autoFireDelay := floor(1000/fps)-AUTOFIRE_DURATION ;连发延时
    autoFireDelay := MyFuns_arrMax([autoFireDelay, 10]) ;设置最小延时
    if (GautoFireKey == ""){
      return  
    } else {
      if (GautoFireFPS > 0){ ;设定连发并开启连发
        MyKey_setAutoFire(Gexe, key1, GautoFireKey, AUTOFIRE_DURATION, autoFireDelay)
        MyKey_setAutoFireState(+1)
      } else { ;设定为单发
        MyKey_setAutoFire(Gexe, key1, GautoFireKey, AUTOFIRE_DURATION)
        MyKey_setAutoFireState(+0)
      }
    }
  }
  
  ;设置技能热键,若技能热键为空则跳过
  setSkillKeys(){
    local ahkExe := "ahk_exe " . Gexe
    local skill := "", myKey := ""
    loop, %NUM_OF_SKILL_KEYS% {
      skill := Gskill%A_Index%
      myKey := myKey%A_Index%
      MyFuns_setHotkey(myKey, skill, ahkExe)
    }
  }

}

/* 运行脚本 
*/
setupGui()
MenuReadPreset("龙2暗黑秘影")